package com.kpmg.datalake.common.utils;

import com.google.common.base.Preconditions;
import com.kpmg.datalake.common.constants.Constants;
import com.kpmg.datalake.common.exception.CustomException;
import java.security.SecureRandom;
import org.apache.commons.codec.binary.Hex;
import org.apache.tomcat.util.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;

/**
 * 加密解密工具类
 * @author Tony
 */
public class EncrypUtil {

	private static final Logger logger = LoggerFactory.getLogger(EncrypUtil.class);

	private EncrypUtil() {
	}
	
	private static final String ENCODING="UTF-8";

	/**
	 * AES加密
	 * @param sSrc
	 * @param key
	 * @return
	 */
	public static String encryptAes(String sSrc, String sKey) {
		try {
			Preconditions.checkNotNull(sSrc, "加密字段为空！");
			Preconditions.checkNotNull(sKey, "秘钥为空！");
			Preconditions.checkArgument(sKey.length() == 16, "加密字段长度不足%s 位!", 16);
			byte[] raw = sKey.getBytes(ENCODING);
			SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
			// "算法/模式/补码方式"
			Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
			cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
			byte[] encrypted = cipher.doFinal(sSrc.getBytes(ENCODING));
			// 此处使用BASE64做转码功能，同时能起到2次加密的作用。
			return new Base64().encodeToString(encrypted);
		} catch (Exception e) {
			logger.error("加密时异常:" + e.getMessage(), e);
			throw new CustomException("加密时异常");
		}
	}

	/**
	 * AES解密
	 * @param sSrc
	 * @param sKey
	 * @return
	 */
	public static String decryptAes(String sSrc, String sKey) {
		try {
			Preconditions.checkNotNull(sSrc, "加密字段为空!");
			Preconditions.checkNotNull(sKey, "秘钥标示位为空!");
			Preconditions.checkArgument(sKey.length() == 16, "加密字段长度不足%s 位!", 16);
			byte[] raw = sKey.getBytes(ENCODING);
			SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
			Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
			cipher.init(Cipher.DECRYPT_MODE, skeySpec);
			// 先用base64解密
			byte[] encrypted1 = new Base64().decode(sSrc);
			byte[] original = cipher.doFinal(encrypted1);
			return new String(original, ENCODING);
		} catch (Exception e) {
			logger.error("解密时异常:" + e.getMessage(), e);
			throw new CustomException("解密时异常");
		}
	}

    public static String encryptSha256(String sSrc) {
        return encryptSha256(sSrc, ENCODING);
    }

	/**
	 * SHA-256加密(不可逆)
	 * @param sSrc
	 * @return
	 */
    public static String encryptSha256(String sSrc, String encoding) {
      MessageDigest digest;
      String encryptStr;
      try {
        Preconditions.checkNotNull(sSrc, "加密字段为空!");
        digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(sSrc.getBytes(encoding));
        encryptStr = Hex.encodeHexString(hash);
      } catch (Exception e) {
        logger.error("SHA-256加密时异常:" + e.getMessage(), e);
        throw new CustomException("SHA-256加密时异常");
      }
      return encryptStr;
	}

	/**
	 * 生成密码salt
	 * @return
	 */
	public static String generateSalt() {
	  String saltStr = "";
    try {
      SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
      byte[] salt = new byte[16];
      random.nextBytes(salt);
      saltStr = Hex.encodeHexString(salt);
    } catch (Exception e) {
      logger.error("生成密码salt时异常:" + e.getMessage(), e);
    }
		return saltStr;
	}

	public static void main(String[] args){
		System.out.println(EncrypUtil.decryptAes("2niWr4iik3jLeIdTgPhudA==",Constants.ENCRY_KEY));
		System.out.println(EncrypUtil.decryptAes("j7n3r1/BLG9aDyEm/s+0rw==",Constants.ENCRY_KEY));
	}
}
